﻿namespace GamePlugin.IO
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Xml;
    using Ionic.Zip;
    using System.Xml.Serialization;
    using GamePlugin.Logics;
    using System.Text;
    using GamePlugin.Logics.Data;
    using System.Drawing;
    using GamePlugin.Logics.Data.Auction;

    public class IOManager
    {
        public static readonly string DataFolderName = "Data";
        public static readonly string ImageFolderName = "Data//Images";
        public static readonly string LogFolderName = "Data//Log";
        public static readonly string AuctionFolderName = "Data//Images//Auction";
        private static IOManager instance = null;

        ~IOManager()
        {
            if (_Writer != null)
                _Writer.WriteLine(DateTime.Now.ToString());
            if (_Stream != null)
                _Stream.Close();
        }

        public static IOManager Instance
        {
            get
            {
                if (IOManager.instance == null)
                {
                    IOManager.instance = new IOManager();
                }
                return IOManager.instance;
            }
        }

        public string DataFolderPath
        {
            get
            {
                string path = Directory.GetCurrentDirectory() + "\\" + DataFolderName;
                if (Directory.Exists(path) == false)
                    Directory.CreateDirectory(path);
                return path;
            }
        }

        public string ImagesFolderPath
        {
            get
            {
                string path = Directory.GetCurrentDirectory() + "\\" + ImageFolderName;
                if (Directory.Exists(path) == false)
                    Directory.CreateDirectory(path);
                return path;
            }
        }

        public string LogFolderPath
        {
            get
            {
                string path = Directory.GetCurrentDirectory() + "\\" + LogFolderName;
                if (Directory.Exists(path) == false)
                    Directory.CreateDirectory(path);
                return path;
            }
        }

        public string AuctionFolderPath
        {
            get
            {
                string path = Directory.GetCurrentDirectory() + "\\" + AuctionFolderName;
                if (Directory.Exists(path) == false)
                    Directory.CreateDirectory(path);
                return path;
            }
        }

        public string GenerateDataPathName()
        {
            for (int i = 0; ; i++)
            {
                string fileName = "AuctionCard" + i.ToString() + ".bmp";
                string path = AuctionFolderPath + "//" + fileName;
                if (File.Exists(path) == false)
                    return path;
            }
        }

        private FileStream _Stream = null;
        private StreamWriter _Writer = null;
        public void Log(string text)
        {
            if (_Writer == null)
            {
                _Stream = new FileStream(this.LogFolderPath + "//" + DateTime.Now.ToString("yyyy_MM_dd_HH_mm") + "_log.txt", FileMode.OpenOrCreate);
                _Writer = new StreamWriter(_Stream);

                _Writer.WriteLine(DateTime.Now.ToString());
            }

            _Writer.WriteLine(DateTime.Now.ToString() + " " + text);
            _Writer.Flush();
        }

        public void CloseLogFile()
        {
            if (_Stream != null)
            {
                _Stream.Close();
                _Stream = null;
            }
            if (_Writer != null)
            {
                _Writer = null;
            }
        }

        public void SaveSearchData(SearchOptionData option, SearchInfoItemList list, string path)
        {
            using (ZipFile zipFile = new ZipFile(Encoding.UTF8))
            {
                int number = 0;
                foreach (SearchItem item in list.Children)
                {
                    using (MemoryStream stream = new MemoryStream())
                    {
                        XmlWriterSettings settings = new XmlWriterSettings();
                        settings.Encoding = Encoding.UTF8;
                        using (XmlWriter writer = XmlWriter.Create(stream, settings))
                        {
                            item.WriteXml(writer);

                            writer.Flush();
                            number++;
                            zipFile.AddEntry(item.SearchInfoName + "#" + number.ToString(), stream.ToArray());
                            writer.Close();
                        }
                        stream.Close();
                    }
                }

                using (MemoryStream stream = new MemoryStream())
                {
                    XmlWriterSettings settings = new XmlWriterSettings();
                    settings.Encoding = Encoding.UTF8;
                    using (XmlWriter writer = XmlWriter.Create(stream, settings))
                    {
                        option.WriteXml(writer);

                        writer.Flush();
                        zipFile.AddEntry("SearchOptionData", stream.ToArray());
                        writer.Close();
                    }
                    stream.Close();
                }

                zipFile.Save(path);
                zipFile.Dispose();
            }
        }

        public void LoadSearchData(SearchOptionData option, SearchInfoItemList list, string path)
        {
            list.Children.Clear();

            ZipFile zipFile = new ZipFile(path, Encoding.UTF8);

            ICollection<ZipEntry> entries = zipFile.Entries;
            foreach (ZipEntry entry in entries)
            {
                using (MemoryStream memory = new MemoryStream())
                {
                    entry.Extract(memory);
                    memory.Position = 0;

                    XmlDocument xmlDoc = new XmlDocument();
                    xmlDoc.Load(memory);
                    if (entry.FileName == "SearchOptionData")
                    {
                        option.ReadXml(xmlDoc);
                    }
                    else
                    {
                        SearchItem item = new SearchItem();
                        item.ReadXml(xmlDoc);
                        list.Children.Add(item);
                    }
                    memory.Close();
                }
            }

            zipFile.Dispose();
        }

        public string SaveImageToFile(Bitmap bitmap)
        {
            string ret = this.ImagesFolderPath + "\\modi.bmp";
            bitmap.Save(ret);
            return ret;
        }

        public void SavePropertyData(LengendItemList legendItemList, PropertyItemList propertyItemList, string path)
        {
            using (ZipFile zipFile = new ZipFile(Encoding.UTF8))
            {
                using (MemoryStream stream = new MemoryStream())
                {
                    XmlWriterSettings settings = new XmlWriterSettings();
                    settings.Encoding = Encoding.UTF8;
                    using (XmlWriter writer = XmlWriter.Create(stream, settings))
                    {
                        legendItemList.WriteXml(writer);

                        writer.Flush();
                        zipFile.AddEntry("LegendItemList", stream.ToArray());
                        writer.Close();
                    }
                    stream.Close();
                }

                using (MemoryStream stream = new MemoryStream())
                {
                    XmlWriterSettings settings = new XmlWriterSettings();
                    settings.Encoding = Encoding.UTF8;
                    using (XmlWriter writer = XmlWriter.Create(stream, settings))
                    {
                        propertyItemList.WriteXml(writer);

                        writer.Flush();
                        zipFile.AddEntry("PropertyItemList", stream.ToArray());
                        writer.Close();
                    }
                    stream.Close();
                }


                zipFile.Save(path);
                zipFile.Dispose();
            }
        }

        public void LoadPropertyData(LengendItemList legendItemList, PropertyItemList propertyItemList, string path)
        {
            ZipFile zipFile = new ZipFile(path, Encoding.UTF8);

            ICollection<ZipEntry> entries = zipFile.Entries;
            foreach (ZipEntry entry in entries)
            {
                using (MemoryStream memory = new MemoryStream())
                {
                    entry.Extract(memory);
                    memory.Position = 0;

                    XmlDocument xmlDoc = new XmlDocument();

                    xmlDoc.Load(memory);
                    if (entry.FileName == "LegendItemList")
                    {
                        legendItemList.ReadXml(xmlDoc);
                    }
                    if (entry.FileName == "PropertyItemList")
                    {
                        propertyItemList.ReadXml(xmlDoc);
                    }
                    memory.Close();
                }
            }

            zipFile.Dispose();
        }

        public void SaveAuctionData(AuctionItemList auctionItemList, string path)
        {
            using (ZipFile zipFile = new ZipFile(Encoding.UTF8))
            {
                using (MemoryStream stream = new MemoryStream())
                {
                    XmlWriterSettings settings = new XmlWriterSettings();
                    settings.Encoding = Encoding.UTF8;
                    using (XmlWriter writer = XmlWriter.Create(stream, settings))
                    {
                        auctionItemList.WriteXml(writer);

                        writer.Flush();
                        zipFile.AddEntry("AuctionItemList", stream.ToArray());
                        writer.Close();
                    }
                    stream.Close();
                }

                zipFile.Save(path);
                zipFile.Dispose();
            }
        }

        public void LoadAuctionData(AuctionItemList auctionItemList, string path)
        {
            ZipFile zipFile = new ZipFile(path, Encoding.UTF8);

            ICollection<ZipEntry> entries = zipFile.Entries;
            foreach (ZipEntry entry in entries)
            {
                using (MemoryStream memory = new MemoryStream())
                {
                    entry.Extract(memory);
                    memory.Position = 0;

                    XmlDocument xmlDoc = new XmlDocument();

                    xmlDoc.Load(memory);
                    if (entry.FileName == "AuctionItemList")
                    {
                        auctionItemList.ReadXml(xmlDoc);
                    }
                    memory.Close();
                }
            }

            zipFile.Dispose();
        }

    }
}
